﻿using System;
using System.IO;
using System.Runtime.InteropServices;

namespace CabConfigProvisioning
{
    public abstract class FciAbstractActions : IFciActions
    {
        public virtual IntPtr FileOpen(string sFilePath, int oflag, int pmode, ref int nError)
        {
            Stream stream;
            if ((oflag & 3) == 1)
            {
                if (!MemoryCache.Instance.TryGetStream(sFilePath, out stream))
                    stream = new FileStream(sFilePath, FileMode.Open, FileAccess.Read);
            }
            else
            {
                stream = new FileStream(sFilePath, FileMode.Create, FileAccess.ReadWrite);
            }
            GCHandle gch = GCHandle.Alloc(stream);
            return (IntPtr)gch;
        }

        public virtual int FileClose(IntPtr hFile, ref int nError)
        {
            Stream stream = FxiHelpers.StreamFromHandle(hFile);
//            stream.Flush();
            stream.Close();
            ((GCHandle)hFile).Free();
            return 0;
        }

        public virtual int FileRead(IntPtr hFile, byte[] buf, int nSize, ref int nError)
        {
            Stream stream = FxiHelpers.StreamFromHandle(hFile);
            return stream.Read(buf, 0, nSize);
        }

        public virtual int FileWrite(IntPtr hFile, byte[] buf, int nSize, ref int nError)
        {
            Stream stream = FxiHelpers.StreamFromHandle(hFile);
            stream.Write(buf, 0, nSize);
//            stream.Flush();
            return nSize;
        }

        public virtual int FileSeek(IntPtr hFile, int nOfs, int nDirection, ref int nError)
        {
            Stream stream = FxiHelpers.StreamFromHandle(hFile);
            return (int)stream.Seek(nOfs, (SeekOrigin)nDirection);
        }

        public virtual int FilePlaced(ref FciCabinetInfo cabinfo, string sFilePath, long cbFile, bool bContinuation)
        {
            return 0;
        }

        public virtual int FileDelete(string sFilePath, ref int nError)
        {
            File.Delete(sFilePath);
            return 0;
        }

        public virtual bool GetTempFile(char[] sTempFilePath, int nTempPathSize)
        {
            string s = Path.GetTempFileName();
            if (s.Length >= nTempPathSize)
                return false;
            Array.Copy(s.ToCharArray(), sTempFilePath, s.Length);
            sTempFilePath[s.Length] = (char) 0;
            return true;
        }

        public virtual bool GetNextCabinet(ref FciCabinetInfo cabinfo, ulong cbprevcab)
        {
            return true;
        }

        public virtual int Status(uint typestatus, ulong cb1, ulong cb2)
        {
            return 0;
        }

        public virtual IntPtr GetOpenInfo(string pszname, out ushort pdate, out ushort ptime, out ushort pattribs, ref int nError)
        {
            Stream stream;
            if (!MemoryCache.Instance.TryGetStream(pszname, out stream, out pdate, out ptime, out pattribs))
            {
                FxiHelpers.GetDosTime(DateTime.Now, out pdate, out ptime);
                pattribs = (int) FileAttributes.Normal;
                stream = new FileStream(pszname, FileMode.Open, FileAccess.Read);
            }
            return (IntPtr)GCHandle.Alloc(stream);
        }

        public virtual void Dispose()
        {
        }

    }
}
